/*
 自定义 Promise 类模块
*/
(function(window){
  // 定义 promise 是三种状态
  const PENDING = 'pending';
  const RESOLVED= 'resolved';
  const REJECTED = 'rejected';
  /* Promise 类 */
  class Promise {
    /*
      promise 构造函数
      executor 执行性函数（同步执行）
    */
    constructor(executor) {
      // 保存当前 promise 对象
      const self = this;
      // 给 promise 对象指定三个属性
      self.status = PENDING;
      // 存储结果数据的属性
      self.data = undefined;
      // 每个元素结构 {onResolved(){},onRejected(){}}
      self.callbacks = [];
      // 定义外部调用时执行器中的两个函数
      function resolve(value) {
        if(self.status !== PENDING) {
          return;
        }
        // 状态改为 resolved
        self.status = RESOLVED;
        self.data = value;
        // 如果有待执行 callback 函数，立即异步执行回到函数 onResolved
        if(self.callbacks.length) {
          setTimeout(() => {
            // 执行队列中所有与成功的回调
            self.callbacks.forEach(callbackObj=>{
              callbackObj.onResolved(value);
            })
          });
        }
      }
      function reject(reason) {
        if(self.status !== PENDING) {
          return;
        }
        // 状态改为 resolved
        self.status = REJECTED;
        self.data = reason;
        if(self.callbacks.length) {
          setTimeout(() => {
            self.callbacks.forEach(callbackObj=>{
              callbackObj.onRejected(reason);
            })
          });
        }
      }
      // 立即同步执行 executor
      try {
        executor(resolve, reject);
      } catch (error) {
        // 如果执行器抛出异常，promise 对象变为 rejected 状态
        reject(error);
      }
    }
    /*
    Promise 原型对象方法
    接收成功和失败的回调函数
    返回一个新的 promise 对象
    */
    then(onResolved, onRejected) {
      // 如果 onResolved 不是函数，则给出默认函数向后传递成功的 value
      onResolved = typeof onResolved === 'function'? onResolved: vlaue=>value;
      // 如果 onRejected 不是函数，则指定默认失败的回调（实现错误/异常传递 的关键点） 向后传递失败的 reason
      onRejected = typeof onRejected === 'function'? onRejected: reason=>{throw reason};

      const self = this;
      return new Promise((resolve, reject)=>{
        /*
          执行指定的回调函数
          根据执行函数返回的结果 改变返回 promise 的状态
        */
        function handle(callback) {
          // 如果抛出异常，返回 promise 的结果为失败
          try {
            const result = callback(self.data);
            // 如果回调函数返回是 promise return 的 promise 结果就是这个函数返回的 promise 结果
            // 如果回调函数返回的不是 promise retrun 的 promise 就会成功，返回结果就是 result
            if(result instanceof Promise) {
              result.then(resolve, reject)
            }else{
              resolve(result)
            }
          } catch (error) {
            reject(error)
          }
        }
        if(self.status === PENDING) {
          // PENDING 等待状态
          // 将回调函数保存起来 并改变返回的 promise 的状态
          self.callbacks.push({
            onResolved(){
              handle(onResolved)
            },
            onRejected() {
              handle(onRejected)
            }
          });
        }else if(self.status === RESOLVED) {
          // RESOLVED 成功状态
          // 异步执行 onResolved 并改变返回的 promise 的状态
          setTimeout(() => {
            handle(onResolved);
          });
        }else {
          // REJECTED 拒绝状态
          // 异步执行 onRejected 并改变返回的 promise 的状态
          setTimeout(() => {
            handle(onRejected);
          });
        }
      })
    }
    /*
      接收一个失败的回调函数
      返回一个新的 promise 对象
    */
    catch(onRejected) {
      return this.then(undefined, onRejected);
    }

    // Promise 函数对象方法
    /*
      返回一个指定结果成功的promise返回
    */
    static resolve(value) {
      return new Promise((resolve, reject)=>{
        // value 是 promise 使用 value 的结果为 promise 的结果
        // vlaue 不是 promise promise 变为成功，数据是 value
        if(value instanceof Promise) {
          value.then(resolve, reject)
        }else{
          resolve(value)
        }
      })
    }
    /*
      返回一个指定 reason 失败的 promise
    */
    static reject(reason) {
      return new Promise((resolve, reject)=>{
        reject(reason)
      })
    }
    /*
      参数接收一个 promise 数组
      返回一个 promise 只有当所有 promise 都成功的时候返回成功的回调
      有一个失败就返回失败的回调
    */
    static all(promises) {
      // 用来保存所有成功的 promise 值的数组
      const values = [];
      // 用来保存成功 promise 的数量
      let count = 0;
      return new Promise((resolve, reject)=>{
        // 遍历所有 promise 获取每个 promise 的结果
        promises.forEach((p, index)=>{
          // 这里如果不是 promise 则转成 promise
          if(!(p instanceof Promise)) {
            p = Promise.resolve(p);
          }
          p.then(value=>{
            values[index] = value;
            count++;
            if(count === promises.length) {
              resolve(values);
            }
          }, reject)
        })
      })
    }
    /*
      参数接收一个 promise 数组
      返回一个promise 其结果由第一个完成的 promise 决定
    */
    static race(promises) {
      return new Promise((resolve, reject)=>{
        promises.forEach(p=>{
          // 这里如果不是 promise 则转成 promise
          if(!(p instanceof Promise)) {
            p = Promise.resolve(p);
          }
          p.then(resolve, reject)
        })
      })
    }
  }
  // 向外部暴露 Promise 函数
  window.Promise = Promise;
})(window);